#include <base/PthreadPool.hpp>
#include <base/Task.hpp>


PthreadPool* PthreadPool::pthread_pool_instance_ = nullptr;
std::mutex PthreadPool::mutex_;

PthreadPool::PthreadPool(int thread_num = THREAD_NUM)
    :thread_num_(thread_num)
{

}

PthreadPool::~PthreadPool()
{
    delete PthreadPool::pthread_pool_instance_;
}

PthreadPool* PthreadPool::GetInstance()
{
    if (PthreadPool::pthread_pool_instance_ == nullptr) {
        PthreadPool::mutex_.lock();
        if (PthreadPool::pthread_pool_instance_== nullptr) {
            PthreadPool::pthread_pool_instance_ = new PthreadPool();
            pthread_pool_instance_ -> InitPthreadPool();
        }
        PthreadPool::mutex_.unlock();
    }
    return PthreadPool::pthread_pool_instance_;
}

void PthreadPool::PthreadFunc(void* ptr)
{
     auto ptr_ = (PthreadPool*)ptr;
     std::unique_lock<std::mutex> ul(ptr_ -> queue_mutex_);
     while (true) {
        ptr_ -> queue_is_empty_cond_.wait(ul, [&]() -> bool {return !ptr_ -> IsEmpty();});
        LogInfo("thread awake!");
        Task* t;
        ptr_ -> PopTask(&t);
        ul.unlock();
        // 执行处理Task的逻辑
        LogInfo("do Task...");
        t -> TaskHandler();
        delete t;
        ul.lock();
     }
}

void PthreadPool::InitPthreadPool()
{
    for (int i = 1; i <= thread_num_; i++) {
        std::thread t(PthreadFunc, (void *)this);
        LogInfo("thread id : %lu", t.get_id());
        t.detach();
    }
    LogInfo("thread_num_ : %d", thread_num_);
    LogInfo("PthreadPool init success");
}

void PthreadPool::PushTask(Task* const task)
{
    LogInfo("PthreadPool push task begin..");
    LogInfo("this pointer : %p", this);
    queue_mutex_.lock();
    queue_.push(task);
    queue_mutex_.unlock();
    LogInfo("PthreadPool push task done..");
    queue_is_empty_cond_.notify_one();
}

void PthreadPool::PopTask(Task** task)
{
    *task = queue_.front();
    queue_.pop();
    LogInfo("PthreadPool pop task");
}

bool PthreadPool::IsEmpty()
{
    bool is_empty = queue_.empty();
    return is_empty;
}
